package protocol.arq;
import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.List;

/**
 * Cette classe permet de recevoir caracteres par caracteres des messages et
 * determine quand les messages sont complets en detectant les flags/fanions aux
 * extremites du message. Quand un message est complet, il est stocke dans une
 * pile.
 * 
 * @author Bertholet Damien & Daoust Julien
 */
public class MessageBuilder {

	private final String fanion;

	private String currentReceive = new String();
	private List<String> messages = new ArrayList<String>();

	/**
	 * Constructeur.
	 * 
	 * @param fanion
	 *            Le fanion utilise.
	 */
	public MessageBuilder(String fanion) {
		this.fanion = fanion;
	}

	/**
	 * Ajoute le caractere.
	 * 
	 * @param c
	 *            Le caractere.
	 * @return True si le message est recu completement. ; False sinon.
	 */
	public boolean add(char c) {
		if(c != '0' && c != '1')
			return false;

		currentReceive += c;
		return pushData();
	}

	/**
	 * Indique si au moins un message a ete recu completement.
	 * 
	 * @return True si au moins un message a ete recu completement. ; False
	 *         sinon.
	 */
	public boolean hasMessage() {
		return !messages.isEmpty();
	}

	/**
	 * Retire de la liste et envoie le premier message recu. S'il n'y a pas de
	 * message, une {@link EmptyStackException} sera envoye.
	 * 
	 * @return Le premier message recu.
	 */
	public String putFirstMessage() {
		if(!hasMessage())
			throw new IllegalAccessError("There's not message.");

		String message = messages.get(0);
		messages.remove(0);
		return message;
	}

	/**
	 * Retourne si le message recu en ce moment est complet.
	 * 
	 * @return Si le message recu en ce moment est complet.
	 */
	private boolean isComplete() {
		return currentReceive.length() > fanion.length() * 2 + 1 &&
		        currentReceive.startsWith(fanion) &&
		        currentReceive.endsWith(fanion);
	}

	/**
	 * Met les informations recus en ce moment dans la pile si le message est
	 * complet.
	 * 
	 * @return True si le message est complet. ; False sinon.
	 */
	private boolean pushData() {
		boolean isComplete = isComplete();
		if(isComplete) {
			messages.add(currentReceive);
			currentReceive = new String();
		}

		return isComplete;
	}
}